/*
 *  Copyright (C) 2004 Cidero, Inc.
 *
 *  Permission is hereby granted to any person obtaining a copy of 
 *  this software to use, copy, modify, merge, publish, and distribute
 *  the software for any non-commercial purpose, subject to the
 *  following conditions:
 *  
 *  The above copyright notice and this permission notice shall be included
 *  in all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
 *  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
 *  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY IN CONNECTION WITH THE SOFTWARE.
 * 
 *  File: $RCSfile: RenderingControl.java,v $
 *
 */

package com.cidero.upnp;

import java.util.logging.Logger;

import org.cybergarage.upnp.*;
import org.cybergarage.upnp.device.InvalidDescriptionException;

import com.cidero.upnp.AbstractService;


/**
 *  RenderingControl service abstract base class. Provides default
 *  implementations for some actions where possible, but mostly just
 *  defines dumb methods that just return 'false' (action not supported).
 *
 *  Notes:
 *
 *  Method header documentation in this class is intended to be the 
 *  'master' copy.  Derived classes should just include
 *  implemention-specific details in their method headers
 */
public class RenderingControl extends AbstractService
{
  private static Logger logger = Logger.getLogger("com.cidero.upnp");

  /**
   *  AV RenderingControl service official UPnP status codes
   *  (Service-specific codes in the range of 700-799). See Cybergarage
   *  UPnPStatus class for generic UPnP codes
   */
	public static final int INVALID_INSTANCE_ID = 702;
  

  /**
   * Constructor
   */
  public RenderingControl( Device device )
    throws InvalidDescriptionException
  {
    super( device );
    
    logger.fine("Entered RenderingControl base class constructor");

    logger.fine("Leaving RenderingControl constructor");
  }
	
  public RenderingControl()
  {
  }

  public String getServiceType()
  {
    return "urn:schemas-upnp-org:service:RenderingControl:1";
  }

  /**
   *  Initialize all required state variables to reasonable values 
   *  Optional device-specific state variables are initialized in the 
   *  derived class instances
   */
  public void initializeStateVariables()
  {
    //logger.fine("Entered - initializing state variables for base class");

    setStateVariable("PresetNameList", "" );
  }

  /** 
   * Convenience routine for RenderingControl service 'LastChange' eventing
   * mechanism.  Sets state variable and sends out a LastChange event
   * in one shot.  The same routine exists for the AVTransport
   * service (don't want to put it in base class since it is service-specific)
   *
   * This method synchronized to be safe since it is often invoked from two
   * threads - the main action processing thread and and asynchronous
   * device monitoring thread.
   *
   * @param varName   State variable name (e.g. 'Volume')
   * @param value     New value for state variable
   */
  public synchronized boolean updateStateVariable( String varName,
                                                   String value )
  {
    //System.out.println("!!!!!!!!!!!!!!!!! UPDATE STATE VAR !!!!!!!!\n");
    //System.out.println("!!!!!! Var, val = " + varName + " " + value );
    //System.out.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
    
    setStateVariable( varName, value );
    getService().updateLastChangeStateVariable();  // evented - triggers send
    return true;
  }

  /**
   * Set volume
   *
   * @param  action  UPnP action object
   *
   *    Action input arguments:
   *      InstanceID 
   *      Channel
   *      DesiredVolume
   *
   *    Action output arguments:
   *
   * NMPR Compliance Notes:
   *   Required Action: Yes
   *
   */
  public boolean actionSetVolume( Action action )
  {
    return false;
  }
  

  /**
   * Get volume
   *
   * @param  action  UPnP action object
   *
   *    Action input arguments:
   *      InstanceID 
   *      Channel
   *      CurrentVolume
   *
   *    Action output arguments:
   *
   * NMPR Compliance Notes:
   *   Required Action: No
   *
   */
  public boolean actionGetVolume( Action action )
  {
    String id = action.getArgumentValue("InstanceID");
    String channel = action.getArgumentValue("Channel");

    logger.fine("GetVolume: Entered, id = " + id + 
                " Channel: " + channel );
    
    // Related variable is 'Volume'...
    action.setArgumentValueFromRelatedStateVariable("CurrentVolume");

    return true;
  }


  /**
   * Get device transport settings
   *
   * @param  action  UPnP action object
   *
   *    Action input arguments:
   *      InstanceID 
   *      Channel
   *
   *    Action output arguments:
   *      CurrentMute
   *
   * NMPR Compliance Notes:
   *   Required Action: No
   *
   */
  public boolean actionSetMute( Action action )
  {
    return false;
  }
  

  /**
   * Get device transport settings
   *
   * @param  action  UPnP action object
   *
   *    Action input arguments:
   *      InstanceID 
   *      Channel
   *
   *    Action output arguments:
   *      CurrentMute
   *
   * NMPR Compliance Notes:
   *   Required Action: Yes
   *
   */
  public boolean actionGetMute( Action action )
  {
    String id = action.getArgumentValue("InstanceID");
    String channel = action.getArgumentValue("Channel");

    logger.fine("GetMute: Entered, id = " + id + 
                " Channel: " + channel );
    
    action.setArgumentValueFromRelatedStateVariable("CurrentMute");

    return true;
  }

  /**
   * Set loudness
   *
   * @param  action  UPnP action object
   *
   *    Action input arguments:
   *      InstanceID 
   *      Channel
   *      DesiredLoudness
   *
   *    Action output arguments:
   *
   * NMPR Compliance Notes:
   *   Required Action: No
   *
   */
  public boolean actionSetLoudness( Action action )
  {
    return false;
  }
  
  /**
   * Get loudness
   *
   * @param  action  UPnP action object
   *
   *    Action input arguments:
   *      InstanceID 
   *      Channel
   *      CurrentLoudness
   *
   *    Action output arguments:
   *
   * NMPR Compliance Notes:
   *   Required Action: No
   *
   */
  public boolean actionGetLoudness( Action action )
  {
    String id = action.getArgumentValue("InstanceID");
    String channel = action.getArgumentValue("Channel");

    logger.fine("GetLoudness: Entered, id = " + id + 
                " Channel: " + channel );
    
    // Related variable is 'Loudness'...
    action.setArgumentValueFromRelatedStateVariable("CurrentLoudness");

    return true;
  }

  /**
   * Describe <code>MethodName</code> method here.
   *
   * @param Action a <code>UPNP Action</code> value
   */

  public boolean actionListPresets( Action action )
  {
    logger.fine("ListPresets: Entered " );
    return false;
  }
  public boolean actionSelectPreset( Action action )
  {
    logger.fine("SelectPreset: Entered " );
    //action.setArgumentValue("ConnectionIDs", "" );
    return false;
  }

  public String errorToString(int code)
  {
    return codeToString( code );
  }

  public static final String codeToString(int code)
  {
    switch (code) 
    {
      case INVALID_INSTANCE_ID: return "Invalid instance id";
    }

    return UPnPStatus.code2String(code);
  }

}

